﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MoneyManagerNET.Presentation.ViewModel.Base;
using System.Diagnostics;
using MoneyManagerNET;
using System.Windows;
using System.ComponentModel;
using System.Reflection;
using System.Windows.Controls;

namespace Mvvm.Infrastructure
{
    public static class ViewLocator
    {
        static TraceSource trace = new TraceSource("MVVM");

        public static void View2ViewModel<TViewModel, TView>() where TViewModel : IViewModel//, TView:Window 
        {
            trace.TraceInformation("Associating ViewModel: [{0}] with View: [{1}]", typeof(TViewModel), typeof(TView));
            associated[typeof(TViewModel)] = typeof(TView);
        }

        static Dictionary<Type, Type> associated = new Dictionary<Type, Type>();
        public static void Associate<T>(this T viewModel, Type windowType) where T : IViewModel
        {
            trace.TraceInformation("Associating ViewModel: [{0}] with View: [{1}]", viewModel.GetType(), windowType);
            associated.Add(viewModel.GetType(), windowType);
        }

        static Type GetUIType(object vm) {
            Type uiType = null;
            
            //explicitly registered
            if(associated.TryGetValue(vm.GetType(), out uiType))
                return uiType;

            //convention
            var typename=vm.GetType().FullName.Replace("ViewModel", "View");
            uiType = Type.GetType(vm.GetType().AssemblyQualifiedName.Replace("Model", string.Empty));
            return uiType;
        }

        //TODO:return UIelement
        public static DependencyObject Locate(this IViewModel viewModel)
        {
            return Locate((object)viewModel);
        }

        public static DependencyObject Locate(object viewModel)
        {

            Type windowType = GetUIType(viewModel);

            //if (windowType == null) 
            //{
            //    var tmpl= ViewModelBinder.DefaultItemTemplate;
            //    var ctrl = new ContentControl(); return tmpl;
            //}
            //else
            {

                var element = (FrameworkElement)Activator.CreateInstance(windowType);

                //use local identity map for the viewModel
                ViewModelBase vmb = viewModel as ViewModelBase;
                if (vmb != null)
                {
                    element.Resources["wrapper"] = vmb.Wrapper;
                }


                element.DataContext = viewModel;

                if (element is Window)
                {
                    var w = element as Window;
                    w.Closing += (o, evt) =>
                    {
                        var ierr = viewModel as IDataErrorInfo;
                        var window = o as Window;

                        if (ierr != null && window.DialogResult.HasValue && window.DialogResult.Value == true)
                        {
                            var error = ierr.Error;
                            var isOk = string.IsNullOrEmpty(error);
                            if (!isOk)
                            {
                                evt.Cancel = isOk;
                                MessageBox.Show(error);
                            }
                        }
                    };

                    //new CancelEventHandler(WindowClosing);
                }

                return element;
            }
        }
    }
}
